import os
# os.environ['ANTHROPIC_LOG'] = 'debug'
model = models[1]
model
'claude-sonnet-4-20250514'

Anthropic provides an interesting example of using tools to mock up a hypothetical ordering system. We’re going to take it a step further, and show how we can dramatically simplify the process, whilst completing more complex tasks.

We’ll start by defining the same mock customer/order data as in Anthropic’s example, plus create a entity relationship between customers and orders:

def _get_orders_customers():
    orders = {
        "O1": dict(id="O1", product="Widget A", quantity=2, price=19.99, status="Shipped"),
        "O2": dict(id="O2", product="Gadget B", quantity=1, price=49.99, status="Processing"),
        "O3": dict(id="O3", product="Gadget B", quantity=2, price=49.99, status="Shipped")}

    customers = {
        "C1": dict(name="John Doe", email="[email protected]", phone="123-456-7890",
                   orders=[orders['O1'], orders['O2']]),
        "C2": dict(name="Jane Smith", email="[email protected]", phone="987-654-3210",
                   orders=[orders['O3']])
    }
    return orders, customers

orders, customers = _get_orders_customers()

We can now define the same functions from the original example – but note that we don’t need to manually create the large JSON schema, since Claudette handles all that for us automatically from the functions directly. We’ll add some extra functionality to update order details when cancelling too.

def get_customer_info(
    customer_id:str # ID of the customer
): # Customer's name, email, phone number, and list of orders
    "Retrieves a customer's information and their orders based on the customer ID"
    print(f'- Retrieving customer {customer_id}')
    return customers.get(customer_id, "Customer not found")

def get_order_details(
    order_id:str # ID of the order
): # Order's ID, product name, quantity, price, and order status
    "Retrieves the details of a specific order based on the order ID"
    print(f'- Retrieving order {order_id}')
    return orders.get(order_id, "Order not found")

def cancel_order(
    order_id:str # ID of the order to cancel
)->bool: # True if the cancellation is successful
    "Cancels an order based on the provided order ID"
    print(f'- Cancelling order {order_id}')
    if order_id not in orders: return False
    orders[order_id]['status'] = 'Cancelled'
    return True

We’re now ready to start our chat.

tools = [get_customer_info, get_order_details, cancel_order]
chat = Chat(model, tools=tools)

We’ll start with the same request as Anthropic showed:

r = chat('Can you tell me the email address for customer C1?')
print(r.stop_reason)
r.content
- Retrieving customer C1
tool_use
[TextBlock(citations=None, text="I'll look up the information for customer C1 to find their email address.", type='text'),
 ToolUseBlock(id='toolu_017Q75iP45WaG7Je7hsEZpWr', input={'customer_id': 'C1'}, name='get_customer_info', type='tool_use')]

Claude asks us to use a tool. Claudette handles that automatically by just calling it again:

r = chat()
contents(r)
'The email address for customer C1 (John Doe) is [email protected].'

Let’s consider a more complex case than in the original example – what happens if a customer wants to cancel all of their orders?

chat = Chat(model, tools=tools)
r = chat('Please cancel all orders for customer C1 for me.')
print(r.stop_reason)
r.content
- Retrieving customer C1
tool_use
[TextBlock(citations=None, text="I'll help you cancel all orders for customer C1. First, let me retrieve the customer's information to see what orders they have.", type='text'),
 ToolUseBlock(id='toolu_01WGzFCErKYyWtTN5xwaCaXu', input={'customer_id': 'C1'}, name='get_customer_info', type='tool_use')]

This is the start of a multi-stage tool use process. Doing it manually step by step is inconvenient, so let’s write a function to handle this for us:


source

Chat.toolloop

 Chat.toolloop (pr, max_steps=10, trace_func:Optional[<built-
                infunctioncallable>]=None, cont_func:Optional[<built-
                infunctioncallable>]=<function noop>, final_prompt='You
                have no more tool uses. Please summarize your findings. If
                you did not complete your goal please tell the user what
                further work needs to be done so they can choose how best
                to proceed.', temp=None, maxtok=4096, maxthinktok=0,
                stream=False, prefill='', tool_choice:Optional[dict]=None)

Add prompt pr to dialog and get a response from Claude, automatically following up with tool_use messages

Type Default Details
pr Prompt to pass to Claude
max_steps int 10 Maximum number of tool requests to loop through
trace_func Optional None Function to trace tool use steps (e.g print)
cont_func Optional noop Function that stops loop if returns False
final_prompt str You have no more tool uses. Please summarize your findings. If you did not complete your goal please tell the user what further work needs to be done so they can choose how best to proceed. Prompt to add if last message is a tool call
temp NoneType None Temperature
maxtok int 4096 Maximum tokens
maxthinktok int 0 Maximum thinking tokens
stream bool False Stream response?
prefill str Optional prefill to pass to Claude as start of its response
tool_choice Optional None Optionally force use of some tool
Exported source
_final_prompt = "You have no more tool uses. Please summarize your findings. If you did not complete your goal please tell the user what further work needs to be done so they can choose how best to proceed."

@patch
@delegates(Chat.__call__)
def toolloop(self:Chat,
             pr, # Prompt to pass to Claude
             max_steps=10, # Maximum number of tool requests to loop through
             trace_func:Optional[callable]=None, # Function to trace tool use steps (e.g `print`)
             cont_func:Optional[callable]=noop, # Function that stops loop if returns False
             final_prompt=_final_prompt, # Prompt to add if last message is a tool call
             **kwargs):
    "Add prompt `pr` to dialog and get a response from Claude, automatically following up with `tool_use` messages"
    init_n = n_msgs = len(self.h)
    r = self(pr, **kwargs)
    for i in range(max_steps):
        if r.stop_reason!='tool_use': break
        if trace_func: trace_func(self.h[n_msgs:]); n_msgs = len(self.h)
        r = self(**kwargs)
        if not (cont_func or noop)(self.h[-2]): break
    
    if r.stop_reason == 'tool_use':
        if trace_func: trace_func(self.h[n_msgs:])
        r = self(final_prompt, **kwargs)
    
    if trace_func: trace_func(self.h[n_msgs:])
    r.steps = self.h[init_n+1:]
    return r

We’ll start by re-running our previous request - we shouldn’t have to manually pass back the tool_use message any more:

chat = Chat(model, tools=tools)
r = chat.toolloop('Can you tell me the email address for customer C1?')
r
- Retrieving customer C1

The email address for customer C1 (John Doe) is [email protected].

  • id: msg_011QZa5DgeFPKXh43SK6gNQz
  • content: [{'citations': None, 'text': 'The email address for customer C1 (John Doe) is [email protected].', 'type': 'text'}]
  • model: claude-sonnet-4-20250514
  • role: assistant
  • stop_reason: end_turn
  • stop_sequence: None
  • type: message
  • usage: {'cache_creation_input_tokens': 0, 'cache_read_input_tokens': 0, 'input_tokens': 787, 'output_tokens': 23, 'server_tool_use': None, 'service_tier': 'standard'}
  • steps: [{'role': 'assistant', 'content': [{'citations': None, 'text': "I'll look up the information for customer C1 to find their email address.", 'type': 'text'}, {'id': 'toolu_01CT9SE7QUq5cfW9VDUnrU5a', 'input': {'customer_id': 'C1'}, 'name': 'get_customer_info', 'type': 'tool_use'}]}, {'role': 'user', 'content': [{'type': 'tool_result', 'tool_use_id': 'toolu_01CT9SE7QUq5cfW9VDUnrU5a', 'content': "{'name': 'John Doe', 'email': '[email protected]', 'phone': '123-456-7890', 'orders': [{'id': 'O1', 'product': 'Widget A', 'quantity': 2, 'price': 19.99, 'status': 'Shipped'}, {'id': 'O2', 'product': 'Gadget B', 'quantity': 1, 'price': 49.99, 'status': 'Processing'}]}"}]}, {'role': 'assistant', 'content': [{'citations': None, 'text': 'The email address for customer C1 (John Doe) is [email protected].', 'type': 'text'}]}]

Let’s see if it can handle the multi-stage process now – we’ll add trace_func=print to see each stage of the process:

chat = Chat(model, tools=tools)
r = chat.toolloop('Please cancel all orders for customer C1 for me.', trace_func=print)
r
- Retrieving customer C1
[{'role': 'user', 'content': 'Please cancel all orders for customer C1 for me.'}, {'role': 'assistant', 'content': [{'citations': None, 'text': "I'll help you cancel all orders for customer C1. First, let me retrieve the customer's information to see what orders they have.", 'type': 'text'}, {'id': 'toolu_01AuPx8R2LAZ3eidgqwVATgQ', 'input': {'customer_id': 'C1'}, 'name': 'get_customer_info', 'type': 'tool_use'}]}, {'role': 'user', 'content': [{'type': 'tool_result', 'tool_use_id': 'toolu_01AuPx8R2LAZ3eidgqwVATgQ', 'content': "{'name': 'John Doe', 'email': '[email protected]', 'phone': '123-456-7890', 'orders': [{'id': 'O1', 'product': 'Widget A', 'quantity': 2, 'price': 19.99, 'status': 'Shipped'}, {'id': 'O2', 'product': 'Gadget B', 'quantity': 1, 'price': 49.99, 'status': 'Processing'}]}"}]}]
- Cancelling order O1
- Cancelling order O2
[{'role': 'assistant', 'content': [{'citations': None, 'text': "I can see that customer C1 (John Doe) has 2 orders:\n- Order O1: Widget A (Status: Shipped)\n- Order O2: Gadget B (Status: Processing)\n\nNow I'll proceed to cancel both orders:", 'type': 'text'}, {'id': 'toolu_01SzEvb1Bd6N5dbSEqtmVARt', 'input': {'order_id': 'O1'}, 'name': 'cancel_order', 'type': 'tool_use'}, {'id': 'toolu_01QJiCVsaqwj4qYoUZXxw5tU', 'input': {'order_id': 'O2'}, 'name': 'cancel_order', 'type': 'tool_use'}]}, {'role': 'user', 'content': [{'type': 'tool_result', 'tool_use_id': 'toolu_01SzEvb1Bd6N5dbSEqtmVARt', 'content': 'True'}, {'type': 'tool_result', 'tool_use_id': 'toolu_01QJiCVsaqwj4qYoUZXxw5tU', 'content': 'True'}]}]
[{'role': 'assistant', 'content': [{'citations': None, 'text': 'Perfect! I have successfully cancelled all orders for customer C1 (John Doe):\n\n✅ **Order O1** (Widget A) - Cancelled successfully\n✅ **Order O2** (Gadget B) - Cancelled successfully\n\nBoth orders have been cancelled as requested. The customer will likely receive confirmation notifications about these cancellations.', 'type': 'text'}]}]

Perfect! I have successfully cancelled all orders for customer C1 (John Doe):

Order O1 (Widget A) - Cancelled successfully ✅ Order O2 (Gadget B) - Cancelled successfully

Both orders have been cancelled as requested. The customer will likely receive confirmation notifications about these cancellations.

  • id: msg_01GxEFQzsDh1R791zQPcqX8X
  • content: [{'citations': None, 'text': 'Perfect! I have successfully cancelled all orders for customer C1 (John Doe):\n\n✅ **Order O1** (Widget A) - Cancelled successfully\n✅ **Order O2** (Gadget B) - Cancelled successfully\n\nBoth orders have been cancelled as requested. The customer will likely receive confirmation notifications about these cancellations.', 'type': 'text'}]
  • model: claude-sonnet-4-20250514
  • role: assistant
  • stop_reason: end_turn
  • stop_sequence: None
  • type: message
  • usage: {'cache_creation_input_tokens': 0, 'cache_read_input_tokens': 0, 'input_tokens': 1017, 'output_tokens': 79, 'server_tool_use': None, 'service_tier': 'standard'}
  • steps: [{'role': 'assistant', 'content': [{'citations': None, 'text': "I'll help you cancel all orders for customer C1. First, let me retrieve the customer's information to see what orders they have.", 'type': 'text'}, {'id': 'toolu_01AuPx8R2LAZ3eidgqwVATgQ', 'input': {'customer_id': 'C1'}, 'name': 'get_customer_info', 'type': 'tool_use'}]}, {'role': 'user', 'content': [{'type': 'tool_result', 'tool_use_id': 'toolu_01AuPx8R2LAZ3eidgqwVATgQ', 'content': "{'name': 'John Doe', 'email': '[email protected]', 'phone': '123-456-7890', 'orders': [{'id': 'O1', 'product': 'Widget A', 'quantity': 2, 'price': 19.99, 'status': 'Shipped'}, {'id': 'O2', 'product': 'Gadget B', 'quantity': 1, 'price': 49.99, 'status': 'Processing'}]}"}]}, {'role': 'assistant', 'content': [{'citations': None, 'text': "I can see that customer C1 (John Doe) has 2 orders:\n- Order O1: Widget A (Status: Shipped)\n- Order O2: Gadget B (Status: Processing)\n\nNow I'll proceed to cancel both orders:", 'type': 'text'}, {'id': 'toolu_01SzEvb1Bd6N5dbSEqtmVARt', 'input': {'order_id': 'O1'}, 'name': 'cancel_order', 'type': 'tool_use'}, {'id': 'toolu_01QJiCVsaqwj4qYoUZXxw5tU', 'input': {'order_id': 'O2'}, 'name': 'cancel_order', 'type': 'tool_use'}]}, {'role': 'user', 'content': [{'type': 'tool_result', 'tool_use_id': 'toolu_01SzEvb1Bd6N5dbSEqtmVARt', 'content': 'True'}, {'type': 'tool_result', 'tool_use_id': 'toolu_01QJiCVsaqwj4qYoUZXxw5tU', 'content': 'True'}]}, {'role': 'assistant', 'content': [{'citations': None, 'text': 'Perfect! I have successfully cancelled all orders for customer C1 (John Doe):\n\n✅ **Order O1** (Widget A) - Cancelled successfully\n✅ **Order O2** (Gadget B) - Cancelled successfully\n\nBoth orders have been cancelled as requested. The customer will likely receive confirmation notifications about these cancellations.', 'type': 'text'}]}]

OK Claude thinks the orders were cancelled – let’s check one:

chat.toolloop('What is the status of order O2?')
- Retrieving order O2

The status of order O2 is Cancelled. This confirms that the cancellation we performed earlier was successful. The order details show:

  • Order ID: O2
  • Product: Gadget B
  • Quantity: 1
  • Price: $49.99
  • Status: Cancelled
  • id: msg_01TU3nxWJxT24yFtxmNwrG72
  • content: [{'citations': None, 'text': 'The status of order O2 is **Cancelled**. This confirms that the cancellation we performed earlier was successful. The order details show:\n\n- **Order ID**: O2\n- **Product**: Gadget B\n- **Quantity**: 1\n- **Price**: $49.99\n- **Status**: Cancelled', 'type': 'text'}]
  • model: claude-sonnet-4-20250514
  • role: assistant
  • stop_reason: end_turn
  • stop_sequence: None
  • type: message
  • usage: {'cache_creation_input_tokens': 0, 'cache_read_input_tokens': 0, 'input_tokens': 1237, 'output_tokens': 74, 'server_tool_use': None, 'service_tier': 'standard'}
  • steps: [{'role': 'assistant', 'content': [{'citations': None, 'text': 'Let me check the current status of order O2 for you.', 'type': 'text'}, {'id': 'toolu_01W6bCBYb9W7ZSdi29XBbST9', 'input': {'order_id': 'O2'}, 'name': 'get_order_details', 'type': 'tool_use'}]}, {'role': 'user', 'content': [{'type': 'tool_result', 'tool_use_id': 'toolu_01W6bCBYb9W7ZSdi29XBbST9', 'content': "{'id': 'O2', 'product': 'Gadget B', 'quantity': 1, 'price': 49.99, 'status': 'Cancelled'}"}]}, {'role': 'assistant', 'content': [{'citations': None, 'text': 'The status of order O2 is **Cancelled**. This confirms that the cancellation we performed earlier was successful. The order details show:\n\n- **Order ID**: O2\n- **Product**: Gadget B\n- **Quantity**: 1\n- **Price**: $49.99\n- **Status**: Cancelled', 'type': 'text'}]}]
chat = Chat(model, tools=tools)
r = chat.toolloop('Please cancel all orders for customer C1 and C2 for me.', max_steps=1)
r
- Retrieving customer C1
- Retrieving customer C2
- Cancelling order O3

Summary of Findings

I successfully completed the goal of canceling all orders for customers C1 and C2. Here’s what I found and accomplished:

Customer C1 (John Doe): - Had 2 orders: O1 and O2 - Both orders were already in “Cancelled” status - No action was needed

Customer C2 (Jane Smith): - Had 1 order: O3 (Gadget B, quantity 2, $49.99) - Order was in “Shipped” status - Successfully cancelled this order

Result: All orders for both customers C1 and C2 are now cancelled. The task has been completed successfully with no further work needed.

  • id: msg_011DBFSXGEyF3hSjwob6CJjM
  • content: [{'citations': None, 'text': '## Summary of Findings\n\nI successfully completed the goal of canceling all orders for customers C1 and C2. Here\'s what I found and accomplished:\n\n**Customer C1 (John Doe):**\n- Had 2 orders: O1 and O2\n- Both orders were already in "Cancelled" status\n- No action was needed\n\n**Customer C2 (Jane Smith):**\n- Had 1 order: O3 (Gadget B, quantity 2, $49.99)\n- Order was in "Shipped" status\n- Successfully cancelled this order\n\n**Result:** All orders for both customers C1 and C2 are now cancelled. The task has been completed successfully with no further work needed.', 'type': 'text'}]
  • model: claude-sonnet-4-20250514
  • role: assistant
  • stop_reason: end_turn
  • stop_sequence: None
  • type: message
  • usage: {'cache_creation_input_tokens': 0, 'cache_read_input_tokens': 0, 'input_tokens': 1275, 'output_tokens': 165, 'server_tool_use': None, 'service_tier': 'standard'}
  • steps: [{'role': 'assistant', 'content': [{'citations': None, 'text': "I'll help you cancel all orders for customers C1 and C2. First, let me retrieve the customer information and their orders.", 'type': 'text'}, {'id': 'toolu_01HHZKUiYYXe9wCiBZS1fHed', 'input': {'customer_id': 'C1'}, 'name': 'get_customer_info', 'type': 'tool_use'}, {'id': 'toolu_01BmAybpXvgAwToPX9y8TRLW', 'input': {'customer_id': 'C2'}, 'name': 'get_customer_info', 'type': 'tool_use'}]}, {'role': 'user', 'content': [{'type': 'tool_result', 'tool_use_id': 'toolu_01HHZKUiYYXe9wCiBZS1fHed', 'content': "{'name': 'John Doe', 'email': '[email protected]', 'phone': '123-456-7890', 'orders': [{'id': 'O1', 'product': 'Widget A', 'quantity': 2, 'price': 19.99, 'status': 'Cancelled'}, {'id': 'O2', 'product': 'Gadget B', 'quantity': 1, 'price': 49.99, 'status': 'Cancelled'}]}"}, {'type': 'tool_result', 'tool_use_id': 'toolu_01BmAybpXvgAwToPX9y8TRLW', 'content': "{'name': 'Jane Smith', 'email': '[email protected]', 'phone': '987-654-3210', 'orders': [{'id': 'O3', 'product': 'Gadget B', 'quantity': 2, 'price': 49.99, 'status': 'Shipped'}]}"}]}, {'role': 'assistant', 'content': [{'citations': None, 'text': "I can see the order information for both customers:\n\n**Customer C1 (John Doe):**\n- Order O1: Already cancelled\n- Order O2: Already cancelled\n\n**Customer C2 (Jane Smith):**\n- Order O3: Currently shipped\n\nSince customer C1's orders (O1 and O2) are already cancelled, I only need to cancel order O3 for customer C2. Let me proceed with cancelling that order:", 'type': 'text'}, {'id': 'toolu_016Xcw9KtMts2GgNLn79LZds', 'input': {'order_id': 'O3'}, 'name': 'cancel_order', 'type': 'tool_use'}]}, {'role': 'user', 'content': [{'type': 'tool_result', 'tool_use_id': 'toolu_016Xcw9KtMts2GgNLn79LZds', 'content': 'True'}]}, {'role': 'assistant', 'content': [{'citations': None, 'text': "Perfect! I've successfully processed the cancellation request:\n\n**Summary:**\n- **Customer C1 (John Doe):** Orders O1 and O2 were already cancelled - no action needed\n- **Customer C2 (Jane Smith):** Order O3 has been successfully cancelled\n\nAll orders for customers C1 and C2 are now cancelled.", 'type': 'text'}]}, {'role': 'user', 'content': 'You have no more tool uses. Please summarize your findings. If you did not complete your goal please tell the user what further work needs to be done so they can choose how best to proceed.'}, {'role': 'assistant', 'content': [{'citations': None, 'text': '## Summary of Findings\n\nI successfully completed the goal of canceling all orders for customers C1 and C2. Here\'s what I found and accomplished:\n\n**Customer C1 (John Doe):**\n- Had 2 orders: O1 and O2\n- Both orders were already in "Cancelled" status\n- No action was needed\n\n**Customer C2 (Jane Smith):**\n- Had 1 order: O3 (Gadget B, quantity 2, $49.99)\n- Order was in "Shipped" status\n- Successfully cancelled this order\n\n**Result:** All orders for both customers C1 and C2 are now cancelled. The task has been completed successfully with no further work needed.', 'type': 'text'}]}]

If we run out of tool loops lets see what happens:

def mydiv(a:int, b:int):
    "Divide two numbers"
    return a / b
chat = Chat(model, tools=[mydiv])
r = chat.toolloop('Try dividing 1 by 0 and see what the error result is', max_steps=2)
r

As expected, attempting to divide 1 by 0 resulted in a ZeroDivisionError: division by zero error. This is the standard Python error that occurs when trying to divide any number by zero, since division by zero is mathematically undefined. The error traceback shows that the error occurred in the mydiv function at the line return a / b when b was 0.

  • id: msg_01MXCSpKQJFqQmR7A4ekUyCu
  • content: [{'citations': None, 'text': 'As expected, attempting to divide 1 by 0 resulted in aZeroDivisionError: division by zeroerror. This is the standard Python error that occurs when trying to divide any number by zero, since division by zero is mathematically undefined. The error traceback shows that the error occurred in themydivfunction at the linereturn a / bwhenbwas 0.', 'type': 'text'}]
  • model: claude-sonnet-4-20250514
  • role: assistant
  • stop_reason: end_turn
  • stop_sequence: None
  • type: message
  • usage: {'cache_creation_input_tokens': 0, 'cache_read_input_tokens': 0, 'input_tokens': 706, 'output_tokens': 92, 'server_tool_use': None, 'service_tier': 'standard'}
  • steps: [{'role': 'assistant', 'content': [{'citations': None, 'text': "I'll try dividing 1 by 0 using the division function to see what error occurs:", 'type': 'text'}, {'id': 'toolu_01BLRi8CHimLLwKbN7LYJ3XC', 'input': {'a': 1, 'b': 0}, 'name': 'mydiv', 'type': 'tool_use'}]}, {'role': 'user', 'content': [{'type': 'tool_result', 'tool_use_id': 'toolu_01BLRi8CHimLLwKbN7LYJ3XC', 'content': 'Traceback (most recent call last):\n File "/Users/jhoward/aai-ws/toolslm/toolslm/funccall.py", line 198, in call_func\n try: return func(**fc_inputs)\n ^^^^^^^^^^^^^^^^^\n File "/Users/jhoward/aai-ws/claudette/claudette/core.py", line 377, in wrapper\n return func(*new_args, **new_kwargs)\n ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n File "/var/folders/51/b2_szf2945n072c0vj2cyty40000gn/T/ipykernel_82009/2257864620.py", line 3, in mydiv\n return a / b\n ~~^~~\nZeroDivisionError: division by zero\n'}]}, {'role': 'assistant', 'content': [{'citations': None, 'text': 'As expected, attempting to divide 1 by 0 resulted in aZeroDivisionError: division by zeroerror. This is the standard Python error that occurs when trying to divide any number by zero, since division by zero is mathematically undefined. The error traceback shows that the error occurred in themydivfunction at the linereturn a / bwhenbwas 0.', 'type': 'text'}]}]

Async tool loop


source

AsyncChat.toolloop

 AsyncChat.toolloop (pr, max_steps=10, trace_func:Optional[<built-
                     infunctioncallable>]=None, cont_func:Optional[<built-
                     infunctioncallable>]=<function noop>,
                     final_prompt='You have no more tool uses. Please
                     summarize your findings. If you did not complete your
                     goal please tell the user what further work needs to
                     be done so they can choose how best to proceed.',
                     temp=None, maxtok=4096, maxthinktok=0, stream=False,
                     prefill='',
                     tool_choice:Union[str,bool,dict,NoneType]=None)

Add prompt pr to dialog and get a response from Claude, automatically following up with tool_use messages

Type Default Details
pr Prompt to pass to Claude
max_steps int 10 Maximum number of tool requests to loop through
trace_func Optional None Function to trace tool use steps (e.g print)
cont_func Optional noop Function that stops loop if returns False
final_prompt str You have no more tool uses. Please summarize your findings. If you did not complete your goal please tell the user what further work needs to be done so they can choose how best to proceed. Prompt to add if last message is a tool call
temp NoneType None Temperature
maxtok int 4096 Maximum tokens
maxthinktok int 0 Maximum thinking tokens
stream bool False Stream response?
prefill str Optional prefill to pass to Claude as start of its response
tool_choice Union None Optionally force use of some tool
orders, customers = _get_orders_customers()
tools = [get_customer_info, get_order_details, cancel_order]
chat = AsyncChat(model, tools=tools)
r = await chat.toolloop('Can you tell me the email address for customer C1?')
r
- Retrieving customer C1

The email address for customer C1 (John Doe) is [email protected].

  • id: msg_0145Cd6is964ivC8rQrkcmES
  • content: [{'citations': None, 'text': 'The email address for customer C1 (John Doe) is [email protected].', 'type': 'text'}]
  • model: claude-sonnet-4-20250514
  • role: assistant
  • stop_reason: end_turn
  • stop_sequence: None
  • type: message
  • usage: {'cache_creation_input_tokens': 0, 'cache_read_input_tokens': 0, 'input_tokens': 787, 'output_tokens': 23, 'server_tool_use': None, 'service_tier': 'standard'}
  • steps: [{'role': 'assistant', 'content': [{'citations': None, 'text': "I'll look up the information for customer C1 to find their email address.", 'type': 'text'}, {'id': 'toolu_016ahSXaFZPCvwUwrMmhej2n', 'input': {'customer_id': 'C1'}, 'name': 'get_customer_info', 'type': 'tool_use'}]}, {'role': 'user', 'content': [{'type': 'tool_result', 'tool_use_id': 'toolu_016ahSXaFZPCvwUwrMmhej2n', 'content': "{'name': 'John Doe', 'email': '[email protected]', 'phone': '123-456-7890', 'orders': [{'id': 'O1', 'product': 'Widget A', 'quantity': 2, 'price': 19.99, 'status': 'Shipped'}, {'id': 'O2', 'product': 'Gadget B', 'quantity': 1, 'price': 49.99, 'status': 'Processing'}]}"}]}, {'role': 'assistant', 'content': [{'citations': None, 'text': 'The email address for customer C1 (John Doe) is [email protected].', 'type': 'text'}]}]

Let’s see if it can handle the multi-stage process now – we’ll add trace_func=print to see each stage of the process:

chat = AsyncChat(model, tools=tools)
r = await chat.toolloop('Please cancel all orders for customer C1 for me.', trace_func=print)
r
- Retrieving customer C1
[{'role': 'user', 'content': 'Please cancel all orders for customer C1 for me.'}, {'role': 'assistant', 'content': [{'citations': None, 'text': "I'll help you cancel all orders for customer C1. First, let me retrieve the customer's information to see what orders they have.", 'type': 'text'}, {'id': 'toolu_01L59zmm81jL6jijGEMW6VGt', 'input': {'customer_id': 'C1'}, 'name': 'get_customer_info', 'type': 'tool_use'}]}, {'role': 'user', 'content': [{'type': 'tool_result', 'tool_use_id': 'toolu_01L59zmm81jL6jijGEMW6VGt', 'content': "{'name': 'John Doe', 'email': '[email protected]', 'phone': '123-456-7890', 'orders': [{'id': 'O1', 'product': 'Widget A', 'quantity': 2, 'price': 19.99, 'status': 'Shipped'}, {'id': 'O2', 'product': 'Gadget B', 'quantity': 1, 'price': 49.99, 'status': 'Processing'}]}"}]}]
- Cancelling order O1
- Cancelling order O2
[{'role': 'assistant', 'content': [{'citations': None, 'text': "I can see that customer C1 (John Doe) has 2 orders:\n- Order O1: Widget A (Status: Shipped)\n- Order O2: Gadget B (Status: Processing)\n\nNow I'll proceed to cancel both orders:", 'type': 'text'}, {'id': 'toolu_01NAe8Rm7D15v1AFJqi8Yz2Y', 'input': {'order_id': 'O1'}, 'name': 'cancel_order', 'type': 'tool_use'}, {'id': 'toolu_01MgXRtEsVUM3zEMnpT3AACy', 'input': {'order_id': 'O2'}, 'name': 'cancel_order', 'type': 'tool_use'}]}, {'role': 'user', 'content': [{'type': 'tool_result', 'tool_use_id': 'toolu_01NAe8Rm7D15v1AFJqi8Yz2Y', 'content': 'True'}, {'type': 'tool_result', 'tool_use_id': 'toolu_01MgXRtEsVUM3zEMnpT3AACy', 'content': 'True'}]}]
[{'role': 'assistant', 'content': [{'citations': None, 'text': 'Perfect! I have successfully cancelled all orders for customer C1 (John Doe):\n\n✅ **Order O1** (Widget A) - Cancelled successfully\n✅ **Order O2** (Gadget B) - Cancelled successfully\n\nBoth orders have been cancelled as requested. The customer will likely receive confirmation notifications about these cancellations.', 'type': 'text'}]}]

Perfect! I have successfully cancelled all orders for customer C1 (John Doe):

Order O1 (Widget A) - Cancelled successfully ✅ Order O2 (Gadget B) - Cancelled successfully

Both orders have been cancelled as requested. The customer will likely receive confirmation notifications about these cancellations.

  • id: msg_01GaspBeDcVGR6NCwFrg8HdM
  • content: [{'citations': None, 'text': 'Perfect! I have successfully cancelled all orders for customer C1 (John Doe):\n\n✅ **Order O1** (Widget A) - Cancelled successfully\n✅ **Order O2** (Gadget B) - Cancelled successfully\n\nBoth orders have been cancelled as requested. The customer will likely receive confirmation notifications about these cancellations.', 'type': 'text'}]
  • model: claude-sonnet-4-20250514
  • role: assistant
  • stop_reason: end_turn
  • stop_sequence: None
  • type: message
  • usage: {'cache_creation_input_tokens': 0, 'cache_read_input_tokens': 0, 'input_tokens': 1017, 'output_tokens': 79, 'server_tool_use': None, 'service_tier': 'standard'}
  • steps: [{'role': 'assistant', 'content': [{'citations': None, 'text': "I'll help you cancel all orders for customer C1. First, let me retrieve the customer's information to see what orders they have.", 'type': 'text'}, {'id': 'toolu_01L59zmm81jL6jijGEMW6VGt', 'input': {'customer_id': 'C1'}, 'name': 'get_customer_info', 'type': 'tool_use'}]}, {'role': 'user', 'content': [{'type': 'tool_result', 'tool_use_id': 'toolu_01L59zmm81jL6jijGEMW6VGt', 'content': "{'name': 'John Doe', 'email': '[email protected]', 'phone': '123-456-7890', 'orders': [{'id': 'O1', 'product': 'Widget A', 'quantity': 2, 'price': 19.99, 'status': 'Shipped'}, {'id': 'O2', 'product': 'Gadget B', 'quantity': 1, 'price': 49.99, 'status': 'Processing'}]}"}]}, {'role': 'assistant', 'content': [{'citations': None, 'text': "I can see that customer C1 (John Doe) has 2 orders:\n- Order O1: Widget A (Status: Shipped)\n- Order O2: Gadget B (Status: Processing)\n\nNow I'll proceed to cancel both orders:", 'type': 'text'}, {'id': 'toolu_01NAe8Rm7D15v1AFJqi8Yz2Y', 'input': {'order_id': 'O1'}, 'name': 'cancel_order', 'type': 'tool_use'}, {'id': 'toolu_01MgXRtEsVUM3zEMnpT3AACy', 'input': {'order_id': 'O2'}, 'name': 'cancel_order', 'type': 'tool_use'}]}, {'role': 'user', 'content': [{'type': 'tool_result', 'tool_use_id': 'toolu_01NAe8Rm7D15v1AFJqi8Yz2Y', 'content': 'True'}, {'type': 'tool_result', 'tool_use_id': 'toolu_01MgXRtEsVUM3zEMnpT3AACy', 'content': 'True'}]}, {'role': 'assistant', 'content': [{'citations': None, 'text': 'Perfect! I have successfully cancelled all orders for customer C1 (John Doe):\n\n✅ **Order O1** (Widget A) - Cancelled successfully\n✅ **Order O2** (Gadget B) - Cancelled successfully\n\nBoth orders have been cancelled as requested. The customer will likely receive confirmation notifications about these cancellations.', 'type': 'text'}]}]
await chat.toolloop('What is the status of order O2?')
- Retrieving order O2

The status of order O2 is Cancelled. This confirms that the cancellation we performed earlier was successful. The order details show:

  • Order ID: O2
  • Product: Gadget B
  • Quantity: 1
  • Price: $49.99
  • Status: Cancelled
  • id: msg_017FWbAVW54uUJZWqUNavgkG
  • content: [{'citations': None, 'text': 'The status of order O2 is **Cancelled**. This confirms that the cancellation we performed earlier was successful. The order details show:\n\n- **Order ID**: O2\n- **Product**: Gadget B\n- **Quantity**: 1\n- **Price**: $49.99\n- **Status**: Cancelled', 'type': 'text'}]
  • model: claude-sonnet-4-20250514
  • role: assistant
  • stop_reason: end_turn
  • stop_sequence: None
  • type: message
  • usage: {'cache_creation_input_tokens': 0, 'cache_read_input_tokens': 0, 'input_tokens': 1237, 'output_tokens': 74, 'server_tool_use': None, 'service_tier': 'standard'}
  • steps: [{'role': 'assistant', 'content': [{'citations': None, 'text': 'Let me check the current status of order O2 for you.', 'type': 'text'}, {'id': 'toolu_01BcHg5GfVTK628WdMqUcW5b', 'input': {'order_id': 'O2'}, 'name': 'get_order_details', 'type': 'tool_use'}]}, {'role': 'user', 'content': [{'type': 'tool_result', 'tool_use_id': 'toolu_01BcHg5GfVTK628WdMqUcW5b', 'content': "{'id': 'O2', 'product': 'Gadget B', 'quantity': 1, 'price': 49.99, 'status': 'Cancelled'}"}]}, {'role': 'assistant', 'content': [{'citations': None, 'text': 'The status of order O2 is **Cancelled**. This confirms that the cancellation we performed earlier was successful. The order details show:\n\n- **Order ID**: O2\n- **Product**: Gadget B\n- **Quantity**: 1\n- **Price**: $49.99\n- **Status**: Cancelled', 'type': 'text'}]}]

If we run out of tool loops lets see what happens:

orders, customers = _get_orders_customers()
chat = AsyncChat(model, tools=tools)
r = await chat.toolloop('Please cancel all orders for customer C1 and C2 for me.', max_steps=1)
r
- Retrieving customer C1
- Retrieving customer C2
- Cancelling order O1
- Cancelling order O2
- Cancelling order O3

Summary of Completed Work

I have successfully completed the requested task of canceling all orders for customers C1 and C2.

What was accomplished:

  • Retrieved customer information for both C1 (John Doe) and C2 (Jane Smith)
  • Identified all orders for both customers:
    • Customer C1: 2 orders (O1 and O2)
    • Customer C2: 1 order (O3)
  • Successfully canceled all 3 orders - each cancellation returned True, confirming success

Final Status:

Goal completed successfully - All orders for customers C1 and C2 have been canceled.

No further work is needed. The task has been completed in full.

  • id: msg_01WXxMSdso6uz673GemzZu8o
  • content: [{'citations': None, 'text': '## Summary of Completed Work\n\nI have successfully completed the requested task of canceling all orders for customers C1 and C2.\n\n### What was accomplished:\n- **Retrieved customer information** for both C1 (John Doe) and C2 (Jane Smith)\n- **Identified all orders** for both customers:\n - Customer C1: 2 orders (O1 and O2)\n - Customer C2: 1 order (O3)\n- **Successfully canceled all 3 orders** - each cancellation returnedTrue, confirming success\n\n### Final Status:\n✅ **Goal completed successfully** - All orders for customers C1 and C2 have been canceled.\n\nNo further work is needed. The task has been completed in full.', 'type': 'text'}]
  • model: claude-sonnet-4-20250514
  • role: assistant
  • stop_reason: end_turn
  • stop_sequence: None
  • type: message
  • usage: {'cache_creation_input_tokens': 0, 'cache_read_input_tokens': 0, 'input_tokens': 1417, 'output_tokens': 175, 'server_tool_use': None, 'service_tier': 'standard'}
  • steps: [{'role': 'assistant', 'content': [{'citations': None, 'text': "I'll help you cancel all orders for customers C1 and C2. First, let me retrieve the customer information and their orders.", 'type': 'text'}, {'id': 'toolu_01Myqhq6vgtUzaDTCjN8hsAa', 'input': {'customer_id': 'C1'}, 'name': 'get_customer_info', 'type': 'tool_use'}, {'id': 'toolu_01BeyBkAcyZJG93RKitKsVVa', 'input': {'customer_id': 'C2'}, 'name': 'get_customer_info', 'type': 'tool_use'}]}, {'role': 'user', 'content': [{'type': 'tool_result', 'tool_use_id': 'toolu_01Myqhq6vgtUzaDTCjN8hsAa', 'content': "{'name': 'John Doe', 'email': '[email protected]', 'phone': '123-456-7890', 'orders': [{'id': 'O1', 'product': 'Widget A', 'quantity': 2, 'price': 19.99, 'status': 'Shipped'}, {'id': 'O2', 'product': 'Gadget B', 'quantity': 1, 'price': 49.99, 'status': 'Processing'}]}"}, {'type': 'tool_result', 'tool_use_id': 'toolu_01BeyBkAcyZJG93RKitKsVVa', 'content': "{'name': 'Jane Smith', 'email': '[email protected]', 'phone': '987-654-3210', 'orders': [{'id': 'O3', 'product': 'Gadget B', 'quantity': 2, 'price': 49.99, 'status': 'Shipped'}]}"}]}, {'role': 'assistant', 'content': [{'citations': None, 'text': "Now I'll cancel all the orders for both customers:\n\n**Customer C1 (John Doe)** has orders: O1 and O2\n**Customer C2 (Jane Smith)** has orders: O3\n\nLet me cancel all these orders:", 'type': 'text'}, {'id': 'toolu_01CZpvVsSQJbFMpuwLGmC5Mb', 'input': {'order_id': 'O1'}, 'name': 'cancel_order', 'type': 'tool_use'}, {'id': 'toolu_01MFZawpjn5jm5cDPyWVZPDD', 'input': {'order_id': 'O2'}, 'name': 'cancel_order', 'type': 'tool_use'}, {'id': 'toolu_01A4L8pXUB16iwxz6GomeQMY', 'input': {'order_id': 'O3'}, 'name': 'cancel_order', 'type': 'tool_use'}]}, {'role': 'user', 'content': [{'type': 'tool_result', 'tool_use_id': 'toolu_01CZpvVsSQJbFMpuwLGmC5Mb', 'content': 'True'}, {'type': 'tool_result', 'tool_use_id': 'toolu_01MFZawpjn5jm5cDPyWVZPDD', 'content': 'True'}, {'type': 'tool_result', 'tool_use_id': 'toolu_01A4L8pXUB16iwxz6GomeQMY', 'content': 'True'}]}, {'role': 'assistant', 'content': [{'citations': None, 'text': 'Perfect! I have successfully canceled all orders for both customers:\n\n**Customer C1 (John Doe):**\n- Order O1 (Widget A) - ✅ Canceled\n- Order O2 (Gadget B) - ✅ Canceled\n\n**Customer C2 (Jane Smith):**\n- Order O3 (Gadget B) - ✅ Canceled\n\nAll 3 orders have been successfully canceled for customers C1 and C2.', 'type': 'text'}]}, {'role': 'user', 'content': 'You have no more tool uses. Please summarize your findings. If you did not complete your goal please tell the user what further work needs to be done so they can choose how best to proceed.'}, {'role': 'assistant', 'content': [{'citations': None, 'text': '## Summary of Completed Work\n\nI have successfully completed the requested task of canceling all orders for customers C1 and C2.\n\n### What was accomplished:\n- **Retrieved customer information** for both C1 (John Doe) and C2 (Jane Smith)\n- **Identified all orders** for both customers:\n - Customer C1: 2 orders (O1 and O2)\n - Customer C2: 1 order (O3)\n- **Successfully canceled all 3 orders** - each cancellation returnedTrue, confirming success\n\n### Final Status:\n✅ **Goal completed successfully** - All orders for customers C1 and C2 have been canceled.\n\nNo further work is needed. The task has been completed in full.', 'type': 'text'}]}]
chat = AsyncChat(model, tools=[mydiv])
r = await chat.toolloop('Try dividing 1 by 0 and see what the error result is', max_steps=2)
r

As expected, attempting to divide 1 by 0 resulted in a ZeroDivisionError: division by zero error. This is the standard Python error that occurs when trying to divide any number by zero, since division by zero is mathematically undefined. The error traceback shows that the error occurred in the mydiv function at the line return a / b when b was 0.

  • id: msg_0143hLbQhPfb7B7P7U7aWni2
  • content: [{'citations': None, 'text': 'As expected, attempting to divide 1 by 0 resulted in aZeroDivisionError: division by zeroerror. This is the standard Python error that occurs when trying to divide any number by zero, since division by zero is mathematically undefined. The error traceback shows that the error occurred in themydivfunction at the linereturn a / bwhenbwas 0.', 'type': 'text'}]
  • model: claude-sonnet-4-20250514
  • role: assistant
  • stop_reason: end_turn
  • stop_sequence: None
  • type: message
  • usage: {'cache_creation_input_tokens': 0, 'cache_read_input_tokens': 0, 'input_tokens': 706, 'output_tokens': 92, 'server_tool_use': None, 'service_tier': 'standard'}
  • steps: [{'role': 'assistant', 'content': [{'citations': None, 'text': "I'll try dividing 1 by 0 using the division function to see what error occurs:", 'type': 'text'}, {'id': 'toolu_016JcuEaTVFa5JXh1nF6S78Y', 'input': {'a': 1, 'b': 0}, 'name': 'mydiv', 'type': 'tool_use'}]}, {'role': 'user', 'content': [{'type': 'tool_result', 'tool_use_id': 'toolu_016JcuEaTVFa5JXh1nF6S78Y', 'content': 'Traceback (most recent call last):\n File "/Users/jhoward/aai-ws/toolslm/toolslm/funccall.py", line 198, in call_func\n try: return func(**fc_inputs)\n ^^^^^^^^^^^^^^^^^\n File "/Users/jhoward/aai-ws/claudette/claudette/core.py", line 377, in wrapper\n return func(*new_args, **new_kwargs)\n ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n File "/var/folders/51/b2_szf2945n072c0vj2cyty40000gn/T/ipykernel_82009/2257864620.py", line 3, in mydiv\n return a / b\n ~~^~~\nZeroDivisionError: division by zero\n'}]}, {'role': 'assistant', 'content': [{'citations': None, 'text': 'As expected, attempting to divide 1 by 0 resulted in aZeroDivisionError: division by zeroerror. This is the standard Python error that occurs when trying to divide any number by zero, since division by zero is mathematically undefined. The error traceback shows that the error occurred in themydivfunction at the linereturn a / bwhenbwas 0.', 'type': 'text'}]}]

Code interpreter

Here is an example of using toolloop to implement a simple code interpreter with additional tools.

from toolslm.shell import get_shell
from fastcore.meta import delegates
import traceback
@delegates()
class CodeChat(Chat):
    imps = 'os, warnings, time, json, re, math, collections, itertools, functools, dateutil, datetime, string, types, copy, pprint, enum, numbers, decimal, fractions, random, operator, typing, dataclasses'
    def __init__(self, model: Optional[str] = None, ask:bool=True, **kwargs):
        super().__init__(model=model, **kwargs)
        self.ask = ask
        self.tools.append(self.run_cell)
        self.shell = get_shell()
        self.shell.run_cell('import '+self.imps)

We have one additional parameter to creating a CodeChat beyond what we pass to Chat, which is ask – if that’s True, we’ll prompt the user before running code.

@patch
def run_cell(
    self:CodeChat,
    code:str,   # Code to execute in persistent IPython session
)->str:
    """Asks user for permission, and if provided, executes python `code` using persistent IPython session.
    Returns: Result of expression on last line (if exists); '#DECLINED#' if user declines request to execute"""
    confirm = f'Press Enter to execute, or enter "n" to skip?\n```\n{code}\n```\n'
    if self.ask and input(confirm): return '#DECLINED#'
    try: res = self.shell.run_cell(code)
    except Exception as e: return traceback.format_exc()
    return res.stdout if res.result is None else res.result

We just pass along requests to run code to the shell’s implementation. Claude often prints results instead of just using the last expression, so we capture stdout in those cases.

sp = f'''You are a knowledgable assistant. Do not use tools unless needed.
Don't do complex calculations yourself -- use code for them.
The following modules are pre-imported for `run_cell` automatically:

{CodeChat.imps}

Never mention what tools you are using. Note that `run_cell` interpreter state is *persistent* across calls.

If a tool returns `#DECLINED#` report to the user that the attempt was declined and no further progress can be made.
In that case, do *not* attempt to run any further code -- stop execution *IMMEDIATELY* and tell the user it was declined.'''
def get_user()->str:
    "Get the username of the user running this session"
    print("Looking up username")
    return 'Jeremy'

In order to test out multi-stage tool use, we create a mock function that Claude can call to get the current username.

model = models[1]
chat = CodeChat(model, tools=[get_user], sp=sp, ask=True, temp=0.3)

Providing a callable to toolloop’s trace_func lets us print out information during the loop:

def _show_cts(h):
    for r in h:
        for o in r.get('content'):
            if hasattr(o,'text'): print(o.text)
            nm = getattr(o, 'name', None)
            if nm=='run_cell': print(o.input['code'])
            elif nm: print(f'{o.name}({o.input})')

…and toolloop’s cont_func callable let’s us provide a function which, if it returns False, stops the loop:

def _cont_decline(c): return nested_idx(c, 'content', 'content') != '#DECLINED#'

Now we can try our code interpreter. We start by asking for a function to be created, which we’ll use in the next prompt to test that the interpreter is persistent.

pr = '''Create a 1-line function `checksum` for a string `s`,
that multiplies together the ascii values of each character in `s` using `reduce`.'''
chat.toolloop(pr, temp=0.2, trace_func=_show_cts, cont_func=_cont_decline)
Press Enter to execute, or enter "n" to skip?
```
checksum = lambda s: functools.reduce(operator.mul, (ord(c) for c in s), 1)

# Test the function
test_string = "hello"
result = checksum(test_string)
print(f"Checksum of '{test_string}': {result}")

# Let's verify by calculating manually
manual = ord('h') * ord('e') * ord('l') * ord('l') * ord('o')
print(f"Manual calculation: {ord('h')} * {ord('e')} * {ord('l')} * {ord('l')} * {ord('o')} = {manual}")
print(f"Results match: {result == manual}")

# Test with another string
test2 = "abc"
result2 = checksum(test2)
print(f"\nChecksum of '{test2}': {result2}")
print(f"Manual: {ord('a')} * {ord('b')} * {ord('c')} = {ord('a') * ord('b') * ord('c')}")
```

checksum = lambda s: functools.reduce(operator.mul, (ord(c) for c in s), 1)

# Test the function
test_string = "hello"
result = checksum(test_string)
print(f"Checksum of '{test_string}': {result}")

# Let's verify by calculating manually
manual = ord('h') * ord('e') * ord('l') * ord('l') * ord('o')
print(f"Manual calculation: {ord('h')} * {ord('e')} * {ord('l')} * {ord('l')} * {ord('o')} = {manual}")
print(f"Results match: {result == manual}")

# Test with another string
test2 = "abc"
result2 = checksum(test2)
print(f"\nChecksum of '{test2}': {result2}")
print(f"Manual: {ord('a')} * {ord('b')} * {ord('c')} = {ord('a') * ord('b') * ord('c')}")
Perfect! Here's the 1-line checksum function:

```python
checksum = lambda s: functools.reduce(operator.mul, (ord(c) for c in s), 1)
```

This function:
- Uses `lambda` to create a concise 1-line function
- Takes a string `s` as input
- Uses `ord(c)` to get the ASCII value of each character `c`
- Uses `functools.reduce` with `operator.mul` to multiply all ASCII values together
- The `1` serves as the initial value (identity for multiplication)

As demonstrated, it correctly calculates the product of all ASCII values in the string.

Perfect! Here’s the 1-line checksum function:

checksum = lambda s: functools.reduce(operator.mul, (ord(c) for c in s), 1)

This function: - Uses lambda to create a concise 1-line function - Takes a string s as input - Uses ord(c) to get the ASCII value of each character c - Uses functools.reduce with operator.mul to multiply all ASCII values together - The 1 serves as the initial value (identity for multiplication)

As demonstrated, it correctly calculates the product of all ASCII values in the string.

  • id: msg_01DXf6WL5XbnxCC2EwgB61LA
  • content: [{'citations': None, 'text': "Perfect! Here's the 1-line checksum function:\n\n```python\nchecksum = lambda s: functools.reduce(operator.mul, (ord(c) for c in s), 1)\n```\n\nThis function:\n- Useslambdato create a concise 1-line function\n- Takes a stringsas input\n- Usesord(c)to get the ASCII value of each characterc\n- Usesfunctools.reducewithoperator.multo multiply all ASCII values together\n- The1serves as the initial value (identity for multiplication)\n\nAs demonstrated, it correctly calculates the product of all ASCII values in the string.", 'type': 'text'}]
  • model: claude-sonnet-4-20250514
  • role: assistant
  • stop_reason: end_turn
  • stop_sequence: None
  • type: message
  • usage: {'cache_creation_input_tokens': 0, 'cache_read_input_tokens': 0, 'input_tokens': 1576, 'output_tokens': 155, 'server_tool_use': None, 'service_tier': 'standard'}
  • steps: [{'role': 'assistant', 'content': [{'id': 'toolu_01PGAKoGi6dBuEpR3ozf8ERz', 'input': {'code': 'checksum = lambda s: functools.reduce(operator.mul, (ord(c) for c in s), 1)\n\n# Test the function\ntest_string = "hello"\nresult = checksum(test_string)\nprint(f"Checksum of \'{test_string}\': {result}")\n\n# Let\'s verify by calculating manually\nmanual = ord(\'h\') * ord(\'e\') * ord(\'l\') * ord(\'l\') * ord(\'o\')\nprint(f"Manual calculation: {ord(\'h\')} * {ord(\'e\')} * {ord(\'l\')} * {ord(\'l\')} * {ord(\'o\')} = {manual}")\nprint(f"Results match: {result == manual}")\n\n# Test with another string\ntest2 = "abc"\nresult2 = checksum(test2)\nprint(f"\\nChecksum of \'{test2}\': {result2}")\nprint(f"Manual: {ord(\'a\')} * {ord(\'b\')} * {ord(\'c\')} = {ord(\'a\') * ord(\'b\') * ord(\'c\')}")'}, 'name': 'run_cell', 'type': 'tool_use'}]}, {'role': 'user', 'content': [{'type': 'tool_result', 'tool_use_id': 'toolu_01PGAKoGi6dBuEpR3ozf8ERz', 'content': "Checksum of 'hello': 13599570816\nManual calculation: 104 * 101 * 108 * 108 * 111 = 13599570816\nResults match: True\n\nChecksum of 'abc': 941094\nManual: 97 * 98 * 99 = 941094\n"}]}, {'role': 'assistant', 'content': [{'citations': None, 'text': "Perfect! Here's the 1-line checksum function:\n\n```python\nchecksum = lambda s: functools.reduce(operator.mul, (ord(c) for c in s), 1)\n```\n\nThis function:\n- Useslambdato create a concise 1-line function\n- Takes a stringsas input\n- Usesord(c)to get the ASCII value of each characterc\n- Usesfunctools.reducewithoperator.multo multiply all ASCII values together\n- The1serves as the initial value (identity for multiplication)\n\nAs demonstrated, it correctly calculates the product of all ASCII values in the string.", 'type': 'text'}]}]

By asking for a calculation to be done on the username, we force it to use multiple steps:

pr = 'Use it to get the checksum of the username of this session.'
chat.toolloop(pr, trace_func=_show_cts)
Looking up username
get_user({})
Press Enter to execute, or enter "n" to skip?
```
username = "Jeremy"
user_checksum = checksum(username)
print(f"Username: {username}")
print(f"Checksum: {user_checksum}")

# Show the calculation breakdown
ascii_values = [ord(c) for c in username]
print(f"ASCII values: {ascii_values}")
print(f"Calculation: {' * '.join(map(str, ascii_values))} = {user_checksum}")
```

username = "Jeremy"
user_checksum = checksum(username)
print(f"Username: {username}")
print(f"Checksum: {user_checksum}")

# Show the calculation breakdown
ascii_values = [ord(c) for c in username]
print(f"ASCII values: {ascii_values}")
print(f"Calculation: {' * '.join(map(str, ascii_values))} = {user_checksum}")
The checksum of the username "Jeremy" is **1,134,987,783,204**.

This is calculated by multiplying the ASCII values: 74 × 101 × 114 × 101 × 109 × 121 = 1,134,987,783,204.

The checksum of the username “Jeremy” is 1,134,987,783,204.

This is calculated by multiplying the ASCII values: 74 × 101 × 114 × 101 × 109 × 121 = 1,134,987,783,204.

  • id: msg_017y7XAVh9AnZEtmdZncN4x3
  • content: [{'citations': None, 'text': 'The checksum of the username "Jeremy" is **1,134,987,783,204**.\n\nThis is calculated by multiplying the ASCII values: 74 × 101 × 114 × 101 × 109 × 121 = 1,134,987,783,204.', 'type': 'text'}]
  • model: claude-sonnet-4-20250514
  • role: assistant
  • stop_reason: end_turn
  • stop_sequence: None
  • type: message
  • usage: {'cache_creation_input_tokens': 0, 'cache_read_input_tokens': 0, 'input_tokens': 2038, 'output_tokens': 70, 'server_tool_use': None, 'service_tier': 'standard'}
  • steps: [{'role': 'assistant', 'content': [{'id': 'toolu_01RvRZY1gQj6rTQ72ZJeEcfK', 'input': {}, 'name': 'get_user', 'type': 'tool_use'}]}, {'role': 'user', 'content': [{'type': 'tool_result', 'tool_use_id': 'toolu_01RvRZY1gQj6rTQ72ZJeEcfK', 'content': 'Jeremy'}]}, {'role': 'assistant', 'content': [{'id': 'toolu_01VRG7yiYrki5StaxU57PSLp', 'input': {'code': 'username = "Jeremy"\nuser_checksum = checksum(username)\nprint(f"Username: {username}")\nprint(f"Checksum: {user_checksum}")\n\n# Show the calculation breakdown\nascii_values = [ord(c) for c in username]\nprint(f"ASCII values: {ascii_values}")\nprint(f"Calculation: {\' * \'.join(map(str, ascii_values))} = {user_checksum}")'}, 'name': 'run_cell', 'type': 'tool_use'}]}, {'role': 'user', 'content': [{'type': 'tool_result', 'tool_use_id': 'toolu_01VRG7yiYrki5StaxU57PSLp', 'content': 'Username: Jeremy\nChecksum: 1134987783204\nASCII values: [74, 101, 114, 101, 109, 121]\nCalculation: 74 * 101 * 114 * 101 * 109 * 121 = 1134987783204\n'}]}, {'role': 'assistant', 'content': [{'citations': None, 'text': 'The checksum of the username "Jeremy" is **1,134,987,783,204**.\n\nThis is calculated by multiplying the ASCII values: 74 × 101 × 114 × 101 × 109 × 121 = 1,134,987,783,204.', 'type': 'text'}]}]